﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace ThirdParty
{
    /// <summary>
    /// QQ登录封装处理
    /// </summary>
    public class QQLoginHandle
    {
        /// <summary>
        /// 应用的AppID
        /// </summary>
        public string AppID { get; set; }
        /// <summary>
        /// 应用的AppKey
        /// </summary>
        public string AppKey { get; set; }
        /// <summary>
        /// 获取当前请求上下文信息
        /// </summary>
        RequestHelper _Request = new RequestHelper();
        /// <summary>
        /// 当获取QQ用户信息成功时 触发
        /// </summary>
        public Action<QQInfo> OnSuccess = null;
        /// <summary>
        /// 当第一次访问时 触发
        /// </summary>
        public Action OnFirstRequest = null;

        public QQLoginHandle(string AppID, string AppKey)
        {
            this.AppID = AppID;
            this.AppKey = AppKey;
        }
        /// <summary>
        /// 执行请求处理
        /// </summary>
        public void DoHandle()
        {
            HttpResponse resp = HttpContext.Current.Response;
            HttpRequest req = HttpContext.Current.Request;
            HttpServerUtility server = HttpContext.Current.Server;

            string thisUrl = req.Url.AbsoluteUri;
            string code = _Request.GetStringQuery("code");

            //第一次访问  
            if (code == "")
            {
                #region 第一步 根据appid 获取 Authorization Code  
                StringBuilder builder = new StringBuilder(500);
                builder.Append("https://graph.qq.com/oauth2.0/authorize?");
                builder.AppendFormat("response_type={0}", "code");
                builder.AppendFormat("&client_id={0}", this.AppID);
                builder.AppendFormat("&redirect_uri={0}", server.UrlDecode(thisUrl));
                builder.AppendFormat("&state={0}", "tianma3798");//用于自身验证  
                builder.AppendFormat("&scope={0}", "do_like");
                //builder.AppendFormat("&display={0}", "mobile"); moblie浏览器使用  

                resp.Redirect(builder.ToString(), false);
                return;
                #endregion
            }
            string state = _Request.GetStringQuery("state");
            //第二次访问  
            if (code != "" && state == "tianma3798")
            {
                #region 第二步 根据Authorization Code 获取Access Token  
                StringBuilder builder = new StringBuilder(500);
                builder.Append("https://graph.qq.com/oauth2.0/token?");
                builder.AppendFormat("grant_type={0}", "authorization_code");
                builder.AppendFormat("&client_id={0}", this.AppID);
                builder.AppendFormat("&client_secret={0}", this.AppKey);
                builder.AppendFormat("&code={0}", code);
                builder.AppendFormat("&redirect_uri={0}", server.UrlDecode(thisUrl));
                //1.获取并解析 access_token 例如：access_token=***&expires_in=***&refresh_token=***  
                string result = NetHelper.Get(builder.ToString());
                string access_token = "";
                try
                {
                    access_token = result.Split('&').FirstOrDefault().Split('=')[1];
                }
                catch (Exception ex)
                {
                    throw new Exception("解析 access_token 是出错：" + ex.Message);
                }
                #endregion

                #region 第三步 根据access_token 获取 OpenID  
                string getOpenIDUrl = "https://graph.qq.com/oauth2.0/me?access_token=" + access_token;
                //1.解析返回结果 中的openid  
                result = NetHelper.Get(getOpenIDUrl);
                List<string> resultList = RegexHelper.Matchs(result, "(?<=\")\\w+(?=\")");
                string openid = resultList.Last();
                #endregion

                #region 第四步 根据OpenID 调用OpenAPI 获取用户信息  
                //第四步 获取用户信息  
                builder.Clear();
                builder.Append("https://graph.qq.com/user/get_user_info?");
                builder.AppendFormat("access_token={0}", access_token);
                builder.AppendFormat("&oauth_consumer_key={0}", this.AppID);
                builder.AppendFormat("&openid={0}", openid);
                string userinfo = NetHelper.Get(builder.ToString());
                #endregion

                try
                {
                    QQInfo info = userinfo.JsonDeserialezer<QQInfo>();
                    if (info == null)
                    {
                        throw new Exception("内部错误：反序列化获取QQInfo对象时失败！");
                    }
                    if (info.ret == "0")
                    {
                        //获取用户信息成功触发
                        info.opendid = openid;
                        info.access_token = access_token;
                        if (this.OnSuccess != null)
                        {
                            this.OnSuccess(info);
                        }
                    }
                    else
                    {
                        throw new Exception(info.msg);
                    }
                }
                catch (Exception ex)
                {
                    //获取用户对象出错  
                    //{"ret":-1,"msg":"client request's parameters are invalid, invalid openid"},可能原因：参数为空  
                    string msg = "获取用户信息失败，当时的qqinfo:" + userinfo + "---------出错原因：" + ex.Message;
                    throw new Exception(msg);
                }
            }
        }
    }
}
